package 作用域相关;


import 抽象语法树节点.抽象语法树;

public class 符号表 {
    public final 全局作用域 全局作用域 = new 全局作用域();

    public 符号表() {
        初始化类型系统();
    }

    protected void 初始化类型系统() {
        全局作用域.定义(new 内置类型符号("int"));
        全局作用域.定义(new 内置类型符号("float"));
        全局作用域.定义(new 内置类型符号("void")); // 伪类型
    }

    public static 符号 解析ID(抽象语法树 节点) {
        var 符号 = 节点.作用域.解析(节点.idToken.getText());
        System.out.println("行 " + 节点.idToken.getLine() + ": 解析 " + 节点.idToken.getText() + " 为 " + 符号);

        if (符号.节点 == null) return 符号; // 一定是预定义符号

        // 如果该符号在局部或全局符号里，则 token 需要在引用之前定义

        var id位置 = 节点.idToken.getTokenIndex();
        var 定义位置 = 符号.节点.idToken.getTokenIndex();
        if (节点.作用域 instanceof 基础作用域 &&
                符号.所在作用域 instanceof 基础作用域 &&
                id位置 < 定义位置) {
            System.err.println("行 " + 节点.idToken.getLine() + ": 错误: 前向引用 " + 节点.idToken.getText());
            return null;
        }

        return 符号;
    }


    /** 'this' and 'super' need to know about enclosing class */
    public static 类符号 取外围类(作用域 符号) {
        while (符号 != null) {
            if (符号 instanceof 类符号) return (类符号) 符号;
            符号 = 符号.取父作用域();
        }

        return null;
    }

    public String toString() {
        return 全局作用域.toString();
    }
}
